<!-- 
    商品列表编辑
 -->
<template>
    <div class="content">
        <div class="shopSpu">
            <h3>商品(Spu)介绍</h3>
            <div class="formdata">
                <el-form ref="ruleFormRef" :model="ruleForm" status-icon :rules="rules" label-width="120px"
                    class="demo-ruleForm">
                    <el-form-item label="商品名称" prop="title">
                        <el-input v-model="ruleForm.title" autocomplete="off" />
                    </el-form-item>
                    <el-form-item label="原始价格" prop="originalPrice" required>
                        <el-input v-model="ruleForm.originalPrice">
                            <template #append>元</template>
                        </el-input>
                    </el-form-item>
                    <el-form-item label="当前价格" prop="price" required>
                        <el-input v-model="ruleForm.price">
                            <template #append>元</template>
                        </el-input>
                    </el-form-item>
                    <el-form-item label="VIP价格" prop="vipPrice" required>
                        <el-input v-model="ruleForm.vipPrice">
                            <template #append>元</template>
                        </el-input>
                    </el-form-item>
                    <el-form-item label="剩余库存">
                        <el-input v-model="ruleForm.stock" :disabled="true" autocomplete="off" />
                    </el-form-item>
                    <el-form-item label="运费模板">
                        <el-select v-model="ruleForm.freightTemplateId" class="m-2" placeholder="选择商品运费模板">
                            <el-option v-for="item in freightSelect" :key="item.id" :label="item.title"
                                :value="item.id" />
                        </el-select>
                    </el-form-item>
                    <el-form-item label="是否在售" prop="status" required>
                        <el-radio-group v-model="ruleForm.status" class="ml-4">
                            <el-radio :label=1 size="large">在售</el-radio>
                            <el-radio :label=0 size="large">下架</el-radio>
                        </el-radio-group>
                    </el-form-item>
                    <el-form-item label="商品图片">
                        <el-upload :file-list="ruleForm.imgList" :headers="headers" action="/upload/admin"
                            list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove"
                            :on-exceed="handleExceed" :on-success="handleImgListSuccess" :before-upload="beforeAvatarUpload" :limit="5">
                            <el-icon>
                                <Plus />
                            </el-icon>
                        </el-upload>
                        <el-dialog v-model="dialogVisible">
                            <img w-full :src="dialogImageUrl" alt="Preview Image" />
                        </el-dialog>
                    </el-form-item>
                    <el-form-item label="商品单位" prop="unit">
                        <el-input v-model="ruleForm.unit" placeholder="件/个/盒" autocomplete="off" />
                    </el-form-item>
                    <el-form-item label="所属类目">
                        <el-cascader :options="categoryData" v-model="ruleForm.categoryId" placeholder="请选择类目" clearable
                            :props="{ checkStrictly: false, children: 'childrenList', value: 'id', label: 'title', emitPath: false }" />
                    </el-form-item>
                    <el-form-item label="商品简介">
                        <el-input v-model="ruleForm.description" autocomplete="off" />
                    </el-form-item>
                    <el-form-item label="商品详情介绍" prop="detail" required>
                        <div class="tinymce">
                            <Tinymce ref="editor" v-model="ruleForm.detail" @getContent="getContent"></Tinymce>
                        </div>
                    </el-form-item>
                </el-form>
            </div>
        </div>
        <div class="shopParams">
            <h4>商品参数</h4>
            <div><el-button type="primary" plain @click="opendDailog(0)">添加</el-button></div>
            <div>
                <el-table :data="ruleForm.attributeList" style="width: 100%;text-align:center;">
                    <el-table-column label="商品参数名" prop="attribute" />
                    <el-table-column prop="value" label="商品参数值" />
                    <el-table-column prop="address" label="操作">
                        <template #default="scope">
                            <el-button type="danger"
                                @click="ruleForm.attributeList.splice(scope.$index, 1)">删除</el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </div>
        </div>
        <div class="specification">
            <h4>规格维度</h4>
            <div><el-button type="primary" plain @click="opendDailog(1)">添加</el-button></div>
            <div>
                <el-table :data="ruleForm.specificationList" style="width: 100%;text-align:center;">
                    <el-table-column label="维度ID" prop="gmtUpdate" />
                    <el-table-column prop="title" label="维度名称" />
                    <el-table-column label="创建时间">
                        <template #default="scope">
                            {{ new Date(scope.row.gmtCreate).friendTime(0) }}
                        </template>
                    </el-table-column>
                    <el-table-column prop="address" label="操作">
                    </el-table-column>
                </el-table>
            </div>
        </div>
        <div class="shopSku">
            <h4>商品(sku)详情</h4>
            <div style="margin-bottom: 20px;">
                <el-button type="primary" :disabled="ruleForm.skuList.length == 0" plain
                    @click="opendDailog(2)">批量定价</el-button>
            </div>
            <div class="tag_box" v-for="item in ruleForm.specificationList" :key="item.title">
                <el-tag type="warning">{{ item.title }}</el-tag>
                <el-tag v-for="tag in item.values" :key="tag" @close="handelClose(item, tag)" closable
                    :disable-transitions="false">{{ tag }}</el-tag>
                <el-input class="input-new-tag" v-if="item.inputSkuTagVisible" ref="inputRef"
                    v-model="item.inputSkuTagValue" size="small" @keyup.enter="handleInputConfirm(item)"
                    @blur="handleInputConfirm(item)" />
                <el-button v-else class="button-new-tag ml-1" size="small" @click="showInput(item)">
                    + 添加
                </el-button>
            </div>
            <div>
                <el-table :data="ruleForm.skuList" :span-method="objectSpanMethod" style="width: 100%;" border
                    :header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }">
                    <el-table-column
                        v-for="(item, index) in ruleForm.specificationList?.filter(v => v.values.length > 0)"
                        :key="index" :prop="'id_' + item.title" :label="item.title" />
                    <el-table-column prop="id" label="SkuID" />
                    <el-table-column label="￥价格(元)" width="180">
                        <template #default="scope">
                            <el-input-number v-model="scope.row.price" :precision="2" />
                        </template>
                    </el-table-column>
                    <el-table-column label="￥VIP价格(元)" width="180">
                        <template #default="scope">
                            <el-input-number v-model="scope.row.vipPrice" :precision="2" />
                        </template>
                    </el-table-column>
                    <el-table-column label="￥吊牌价(元)" width="180">
                        <template #default="scope">
                            <el-input-number v-model="scope.row.originalPrice" :precision="2" />
                        </template>
                    </el-table-column>
                    <el-table-column label="库存(件)" width="180">
                        <template #default="scope">
                            <el-input-number v-model="scope.row.stock" :precision="2" />
                        </template>
                    </el-table-column>
                    <el-table-column label="重量(克)" width="180">
                        <template #default="scope">
                            <el-input-number v-model="scope.row.weight" :precision="2" />
                        </template>
                    </el-table-column>
                    <el-table-column label="SKU图片" width="180">
                        <template #default="scope">
                            <div @click="imgIndex = scope.$index">
                                <el-upload class="avatar-uploader" action="/upload/admin" :headers="headers"
                                    :show-file-list="false" :on-success="handleAvatarSuccess"
                                    :before-upload="beforeAvatarUpload">
                                    <img v-if="scope.row.img" :src="scope.row.img" width="100" height="100">
                                    <el-button v-else type="primary" :icon="Upload">上传</el-button>
                                </el-upload>
                            </div>
                        </template>
                    </el-table-column>
                    <el-table-column label="条形码" width="240">
                        <template #default="scope">
                            <el-input v-model="scope.row.barCode">
                                <template #append>
                                    <span style="cursor: pointer;" @click="scope.row.barCode = +new Date()">随机</span>
                                </template>
                            </el-input>
                        </template>
                    </el-table-column>
                </el-table>
            </div>
        </div>
        <div class="footer">
            <el-button size="large" type="primary" @click="handleCancel">关闭</el-button>
            <el-button size="large" type="primary" @click="submitForm(ruleFormRef)">保存商品</el-button>
        </div>

        <div>
            <el-dialog v-model="dialogFormVisible" :title="dialogTitle" width="30%">
                <!-- 商品参数内容 -->
                <div v-if="opendDailogNum == 0">
                    <el-form :model="attributForm" label-width="110px" label-position="left" status-icon
                        style="padding:0px 20px 0px 30px;">
                        <el-form-item label="商品参数名称" required>
                            <el-input v-model="attributForm.attribute" autocomplete="off" />
                        </el-form-item>
                        <el-form-item label="商品参数值" required>
                            <el-input v-model="attributForm.value" autocomplete="off" />
                        </el-form-item>
                    </el-form>
                </div>
                <!-- 规格维度 -->
                <div v-if="opendDailogNum == 1 || opendDailogNum == 3">
                    <el-form :model="specificationForm" label-width="110px" label-position="left" status-icon
                        style="padding:0px 20px 0px 30px;">
                        <el-form-item label="类型名称">
                            <el-input v-model="specificationForm.title" autocomplete="off" />
                        </el-form-item>
                    </el-form>
                </div>
                <!-- 批量定价 -->
                <div v-if="opendDailogNum == 2">
                    <el-form :model="skuForm" label-width="110px" label-position="left" status-icon
                        style="padding:0px 20px 0px 30px;">
                        <el-form-item label="现价(￥)">
                            <el-input-number v-model="skuForm.price" :precision="2" />
                        </el-form-item>
                        <el-form-item label="VIP价格(￥)">
                            <el-input-number v-model="skuForm.vipPrice" :precision="2" />
                        </el-form-item>
                        <el-form-item label="吊牌价(￥)">
                            <el-input-number v-model="skuForm.originalPrice" :precision="2" />
                        </el-form-item>
                    </el-form>
                </div>
                <template #footer>
                    <span class="dialog-footer">
                        <el-button @click="dialogFormVisible = false">取消</el-button>
                        <el-button type="primary" @click="handelConfirm">
                            确认
                        </el-button>
                    </span>
                </template>
            </el-dialog>
        </div>
    </div>
</template>

<script lang="ts" setup>
import { reactive, ref, nextTick } from 'vue'
import { post } from "@/http/request";
import { Delete, Plus, ZoomIn, Upload } from '@element-plus/icons-vue'
import type { UploadFile, FormInstance, UploadProps } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus';
import Tinymce from "@/components/tinymce/Tinymce.vue";
import cookie from "js-cookie";
import "@/utils/DateFormatter";
import { ClassProductAddEdit, ClassAttributeList, ClassSpecificationList, ClassSkuList } from "#/index";
import { toArray } from 'lodash';
import { useRouter, useRoute } from "vue-router";
import { useTagsStore } from "@/stores/tags";

const router = useRouter()
const route = useRoute()
const store = useTagsStore()

const dialogFormVisible = ref(false)//弹窗是否显示
const dialogTitle = ref('')//弹窗标题
const opendDailogNum = ref(0)//判断弹窗内容

//商品参数弹窗表单
const attributForm = reactive(new ClassAttributeList())//商品参数表单数据
const clearAttributForm = reactive({ ...attributForm })
const specificationForm = reactive(new ClassSpecificationList())//规格维度
const clearSpecification = reactive({ ...specificationForm })
const skuForm = reactive(new ClassSkuList())//批量定价
const clearSkuForm = reactive({ ...skuForm })
const inputRef = ref()
const skuLength = ref(0)
const categoryData = ref([])//类目数据
const freightSelect = ref<{ id: number, title: string }[]>([])//运费模板数据
const dialogImageUrl = ref('')//图片列表查看大图
const dialogVisible = ref(false)//图片列表查看大图弹窗显示隐藏
const disabled = ref(false)

const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive(new ClassProductAddEdit())

// 商品参数添加||规格维度添加||批量定价 打开弹窗按钮事件
function opendDailog(num: number) {
    if (num == 0) {
        Object.assign(attributForm, clearAttributForm)
        opendDailogNum.value = 0
        dialogTitle.value = '设置商品参数'
    } else if (num == 1) {
        // 规格维度添加
        Object.assign(specificationForm, clearSpecification)
        opendDailogNum.value = 1
        dialogTitle.value = '创建规格维度'
    } else if (num == 2) {
        opendDailogNum.value = 2
        Object.assign(skuForm, clearSkuForm)
        dialogTitle.value = '批量定价'
    }
    nextTick(() => {
        dialogFormVisible.value = true
    })
}

// 弹窗确定按钮
function handelConfirm() {
    switch (opendDailogNum.value) {
        case 0://商品参数添加
            if (attributForm.attribute == "" || attributForm.value == "") return ElMessage.warning("参数名称或参数值为空")
            if (ruleForm.attributeList.some(item => item.attribute === attributForm.attribute)) return ElMessage.warning("参数名称重复")
            ruleForm.attributeList.push({ ...attributForm })
            ElMessage.success('添加成功')
            break;
        case 1://规格维度添加
            if (ruleForm.specificationList.some(item => item.title === specificationForm.title)) return ElMessage.warning("规格维度类型名称重复")
            if (specificationForm.title == "") return ElMessage.warning("请输入类型名称")
            specificationForm.gmtCreate = +new Date()
            specificationForm.gmtUpdate = +new Date()
            ruleForm.specificationList.push({ ...specificationForm })
            ElMessage.success('添加成功')
            break;
        case 2://批量定价
            if (skuForm.vipPrice > skuForm.price || skuForm.price > skuForm.originalPrice) return ElMessage.warning("必须VIP价<=现价<=原价")
            ruleForm.skuList.map(item => Object.assign(item, {
                price: skuForm.price,
                vipPrice: skuForm.vipPrice,
                originalPrice: skuForm.originalPrice
            }))
            break;
        default:
            break;
    }
    dialogFormVisible.value = false
}

// tag删除
function handelClose(item: ClassSpecificationList, tag: string) {
    item.values.splice(item.values.indexOf(tag), 1)
    ruleForm.specificationList.length != 0 ? handelSkuList() : ruleForm.skuList.length = 0
}

// tag添加
function handleInputConfirm(item: ClassSpecificationList) {
    let inputSkuTagValue = item.inputSkuTagValue
    item.values = toArray(item.values)//将类数组转型
    if (inputSkuTagValue) {
        //往当前的tags数组添加tag
        item.values.push(inputSkuTagValue)
    }
    handelSkuList()
    item.inputSkuTagVisible = false
    item.inputSkuTagValue = ""
}

// tag显示输入框
function showInput(item: ClassSpecificationList) {
    item.inputSkuTagVisible = true
    nextTick(() => {
        inputRef.value[0]!.input!.focus()//聚焦
    })
}

// 动态生成sku列表
function handelSkuList() {
    let valueList = ruleForm.specificationList.filter(item => item.values.length).map(item => item.values)
    let titles = ruleForm.specificationList.filter(item => item.values.length).map(item => item.title)
    if (valueList.length == 0) return ruleForm.skuList = []
    // 使用笛卡尔积算法将数据进行交叉处理
    let arr = valueList.reduce((total: string[][], curr) => {
        let temp: string[][] = []
        total.forEach(item => {
            curr.forEach(val => {
                temp.push(item.concat([val]))
            })
        })
        return temp
    }, [[]])

    // 进行数据拼接
    let list = arr.map(item => {
        let obj: any = reactive(new ClassSkuList())
        item.forEach((val: string, index: number) => {
            obj['id_' + titles[index]] = val
            obj['title'] = item.join(',')
            obj.specification += ruleForm.specificationList[index].title + '_' + val + ','
        })
        return obj;
    })
    skuLength.value = list.length
    ruleForm.skuList.length = 0
    Object.assign(ruleForm.skuList, list)
}


// 跨行跨列
function objectSpanMethod({ rowIndex, columnIndex }: { rowIndex: number, columnIndex: number }) {
    let specList = ruleForm.specificationList.filter(item => item.values.length > 0) //过滤掉规格维度数组中values有没有值
    if (columnIndex < specList.length - 1) { //对要跨行的列进行计算，排除最后一个属性列(最后一个属性不存在)
        let rowSpanNum = 1 //跨行的数量
        for (let index = columnIndex + 1; index < specList.length; index++) {
            rowSpanNum *= specList[index].values.length //跨行的数量-后面属性值数量的成绩
        }
        if (rowIndex % rowSpanNum === 0) { //每次跨行的数量相同,所以当前行索引号%跨行数量==0就是要跨行的开始
            return { rowspan: rowSpanNum, colspan: 1 };
        } else {
            return { rowspan: 0, colspan: 0 };
        }
    }
}

// sku列表上传图片
const imgIndex = ref()
const handleAvatarSuccess: UploadProps['onSuccess'] = (
    res,
    uploadFile
) => {
    ruleForm.skuList[imgIndex.value].img = res.url
}

const rules = reactive({
    // 商品名称
    title: [{ required: true, message: '请输入商品名称', trigger: 'blur' },],
    // 原始价格
    originalPrice: [{ required: true, message: '原始价格为空', trigger: 'blur' },],
    // 当前价格
    price: [{ required: true, message: '当前价格为空', trigger: 'blur' },],
    // vIP价格
    vipPrice: [{ required: true, message: 'vip价格为空', trigger: 'blur' },],
    // 商品单位
    unit: [{ required: true, message: '请输入商品单位', trigger: 'blur' },],

})

// 点击关闭按钮，关闭标签页并返回商品列表
function handleCancel() {
    loadData()
    store.removeTagByPath(route.fullPath)
    router.push({ name: "productlist" })
}

// 保存商品请求
const submitForm = (formEl: FormInstance | undefined) => {
    if (!formEl) return
    formEl.validate((valid) => {
        if (valid) {
            let data = reactive({
                _gp: "admin.product",
                _mt: "edit",
                spuDTO: JSON.stringify(ruleForm),
            })
            post(data).then(res => {
                console.log(res);
                let { errno, errmsg } = res
                if (200 == errno) {
                    ElMessageBox.confirm(
                        '保存商品成功，是否留在当前页面?',
                        '提示',
                        {
                            confirmButtonText: '留在当前页面',
                            cancelButtonText: '返回商品列表',
                            type: 'warning',
                        }
                    ).catch(() => {
                        router.push({ name: "productlist" })
                    })
                } else {
                    ElMessage.error(errmsg)
                }
            })
        } else {
            console.log('error submit!')
            return false
        }
    })
}

// 富文本框
const getContent = (v: string) => {     //子传父商品详情介绍数据
    ruleForm.detail = v
}

// 商品图片上传
// 上传图片需配置的请求头
const headers = reactive({
    AdminToken: cookie.get('token')
})

// 上传图片超出触发提示
function handleExceed() {
    ElMessage.error("一次最多上传5张")
}

// 图片上传成功前的钩子函数
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
    if (rawFile.size / 1024 / 1024 > 1) {
        ElMessage.error('图片大小不能超过1MB!')
        return false
    }
    return true
}

// 图片上传成功的回调
const handleImgListSuccess: UploadProps['onSuccess'] = (response) => {
    ruleForm.img = response.url
    ruleForm.imgList.push(response.url)
}

// 移除图片触发
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
    console.log(uploadFile, uploadFiles)
}

// 点击上传成功的图片查看
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
    dialogImageUrl.value = uploadFile.url!
    dialogVisible.value = true
}

// 请求运费模板数据
function freightInit() {
    post({ _gp: "admin.freight", _mt: "list", }).then(res => {
        // console.log(res);
        let { data, errno, errmsg } = res
        if (200 == errno) {
            freightSelect.value = data
        } else {
            ElMessage.error(errmsg)
        }
    })
}
freightInit()

// 请求弹窗类目数据
function popCategory() {
    let data = {
        _gp: 'admin.category',
        _mt: 'categoryTree'
    }
    post(data).then(res => {
        // console.log(res);
        let { data, errno, errmsg } = res
        if (200 == errno) {
            categoryData.value = data
        } else {
            ElMessage.error(errmsg)
        }
    })
}
popCategory()

// 初始化页面数据
function loadData() {
    let data = reactive({
        _gp: "admin.product",
        _mt: "detail",
        spuId: route.params.id,
    })
    post(data).then(res => {
        let { data, errmsg, errno } = res
        if (200 == errno) {
            console.log(res);

            let imgList = data.imgList.map((img: string, index: number) => {
                return { name: index + "", url: img }
            })
            data.imgList.length = 0
            data.imgList.push(...imgList)


            data.specificationList.map((item: any, index: number) => {
                let sku = data.skuList.map((val: any) => {
                    return val.title.split(",")[index].split(" ");
                });
                return Object.assign(item, { values: [...new Set(sku.flat())] });
            });

            data.skuList.forEach((sku: any) => {
                let spec = sku.specification || '' //取出字段
                spec.split(',').map((item: any) => item.split('_')).forEach((value: any) => {
                    let title = value[0]
                    let val = value[1]
                    sku["id_" + title] = val
                    let findSpec = data.specificationList.find((e: any) => e.title == title) //找到对应的规格
                    if (-1 == findSpec?.values.indexOf(val)) { //去重
                        findSpec.values.push(val)
                    }
                })
            })

            Object.assign(ruleForm, data)
        } else {
            ElMessage.error(errmsg)
        }
    })
}
loadData()

</script>

<style lang="less" scoped>
.el-form-item {
    margin-bottom: 20px !important;
}

.content {
    padding: 20px 0;
}

.shopSpu,
.shopSku,
.shopParams,
.specification {
    width: 100%;
    box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
    padding: 20px;
    box-sizing: border-box;
}

.shopSpu {
    padding: 30px 0;

    h3 {
        margin: 0;
        padding: 20px;
    }

    .formdata {
        padding: 0 20px 0 60px;
    }
}

.tinymce {
    width: 100%;
}

.footer {
    text-align: right;
    padding-top: 20px;
}

.tag_box {
    margin-bottom: 20px;

    .el-tag {
        margin-right: 10px;
    }

    .input-new-tag {
        width: 150px;
    }
}
</style>